﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Область СлужебныйПрограммныйИнтерфейс

// Получает сообщение обмена из информационной базы корреспондента через веб-сервис во временный каталог пользователя
// ОС.
//
// Параметры:
//  Отказ                   - Булево - флаг отказа; поднимается в случае возникновения ошибки.
//  УзелИнформационнойБазы  - ПланОбменаСсылка - узел плана обмена, для которого выполняется получение сообщения обмена.
//  ИдентификаторФайла      - УникальныйИдентификатор - идентификатор файла.
//  ДлительнаяОперация      - Булево - признак использования длительное операции.
//  ИдентификаторОперации   - УникальныйИдентификатор - уникальный идентификатор длительной операции.
//  ПараметрыАутентификации - Структура - содержит параметры аутентификации на веб-сервисе (Пользователь, Пароль).
//
//  Возвращаемое значение:
//   Структура со следующими ключи:
//     * ИмяВременногоКаталогаСообщенийОбмена - полное имя каталога обмена, в которое было загружено сообщение обмена.
//     * ИмяФайлаСообщенияОбмена              - полное имя файла сообщения обмена.
//     * ИдентификаторФайлаПакетаДанных       - дата изменения файла сообщения обмена.
//
Функция ПолучитьСообщениеОбменаВоВременныйКаталогИзИнформационнойБазыКорреспондентаЧерезВебСервис(
											Отказ,
											УзелИнформационнойБазы,
											ИдентификаторФайла,
											ДлительнаяОперация,
											ИдентификаторОперации,
											ПараметрыАутентификации = Неопределено) Экспорт
	
	ОбменДаннымиСервер.ПроверитьВозможностьВыполненияОбменов();
	
	ОбменДаннымиСервер.ПроверитьИспользованиеОбменаДанными();
	
	УстановитьПривилегированныйРежим(Истина);
	
	// Возвращаемое значение функции.
	Результат = Новый Структура;
	Результат.Вставить("ИмяВременногоКаталогаСообщенийОбмена", "");
	Результат.Вставить("ИмяФайлаСообщенияОбмена",              "");
	Результат.Вставить("ИдентификаторФайлаПакетаДанных",       Неопределено);
	
	// Параметры, которые будут определены в функции.
	ИмяКаталогаСообщенияОбмена = "";
	ИмяФайлаСообщенияОбмена = "";
	ДатаФайлаСообщенияОбмена = Дата('00010101');
	
	СтруктураНастроекОбмена = ОбменДаннымиСервер.НастройкиОбменаДляУзлаИнформационнойБазы(
		УзелИнформационнойБазы, "ПолучениеСообщенияОбмена", Перечисления.ВидыТранспортаСообщенийОбмена.WS, Ложь);
		
	СтруктураНастроекОбмена.КлючСообщенияЖурналаРегистрации =
		ОбменДаннымиСервер.КлючСообщенияЖурналаРегистрации(УзелИнформационнойБазы, Перечисления.ДействияПриОбмене.ЗагрузкаДанных);
	СтруктураНастроекОбмена.ДействиеПриОбмене = Неопределено;
		
	ПараметрыПрокси = Новый Структура;
	ПараметрыПрокси.Вставить("ПараметрыАутентификации", ПараметрыАутентификации);
	
	Прокси = Неопределено;
	СостояниеНастройки = Неопределено;
	СообщениеОбОшибке = "";
	ИнициализироватьWSПроксиДляУправленияОбменомДанными(Прокси, 
		СтруктураНастроекОбмена, ПараметрыПрокси, Отказ, СостояниеНастройки, СообщениеОбОшибке);
	
	Если Отказ Тогда
		ОбменДаннымиСервер.ЗаписьЖурналаРегистрацииОбменаДанными(СообщениеОбОшибке, СтруктураНастроекОбмена, Истина);
		Возврат Результат;
	КонецЕсли;
	
	ПараметрыОбмена = Новый Структура;
	ПараметрыОбмена.Вставить("ИдентификаторФайла",          ИдентификаторФайла);
	ПараметрыОбмена.Вставить("ДлительнаяОперация",          ДлительнаяОперация);
	ПараметрыОбмена.Вставить("ИдентификаторОперации",       ИдентификаторОперации);
	ПараметрыОбмена.Вставить("ДлительнаяОперацияРазрешена", Истина);
	
	Попытка
		
		ВыполнитьВыгрузкуДанных(Прокси, ПараметрыПрокси.ТекущаяВерсия, СтруктураНастроекОбмена, ПараметрыОбмена);
		
		ИдентификаторФайла = ПараметрыОбмена.ИдентификаторФайла;
		ДлительнаяОперация = ПараметрыОбмена.ДлительнаяОперация;
		ИдентификаторОперации = ПараметрыОбмена.ИдентификаторОперации;
		
	Исключение
		
		Отказ = Истина;
		Сообщение = НСтр("ru = 'При выгрузке данных возникли ошибки во второй информационной базе: %1'", ОбщегоНазначения.КодОсновногоЯзыка());
		Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(Сообщение,
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		
		ОбменДаннымиСервер.ЗаписьЖурналаРегистрацииОбменаДанными(Сообщение, СтруктураНастроекОбмена, Истина);
		
		Возврат Результат;
	КонецПопытки;
	
	Если ПараметрыОбмена.ДлительнаяОперация Тогда
		ОбменДаннымиСервер.ЗаписьЖурналаРегистрацииОбменаДанными(НСтр("ru = 'Ожидание получения данных от базы-корреспондента...'",
			ОбщегоНазначения.КодОсновногоЯзыка()), СтруктураНастроекОбмена);
		Возврат Результат;
	КонецЕсли;
	
	Попытка
		ИмяФайлаИзСервисаПередачиФайлов = ПолучитьФайлИзХранилищаВСервисе(
			Новый УникальныйИдентификатор(ПараметрыОбмена.ИдентификаторФайла),
			СтруктураНастроекОбмена.УзелИнформационнойБазы,, ПараметрыАутентификации);
	Исключение
		
		Отказ = Истина;
		Сообщение = НСтр("ru = 'Возникли ошибки при получении сообщения обмена из сервиса передачи файлов: %1'", ОбщегоНазначения.КодОсновногоЯзыка());
		Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(Сообщение,
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		
		ОбменДаннымиСервер.ЗаписьЖурналаРегистрацииОбменаДанными(Сообщение, СтруктураНастроекОбмена, Истина);
		
		Возврат Результат;
	КонецПопытки;
	
	Попытка
		ИмяКаталогаСообщенияОбмена = ОбменДаннымиСервер.СоздатьВременныйКаталогСообщенийОбмена();
	Исключение
		Отказ = Истина;
		Сообщение = НСтр("ru = 'При получении сообщения обмена возникли ошибки: %1'", ОбщегоНазначения.КодОсновногоЯзыка());
		Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(Сообщение,
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		
		ОбменДаннымиСервер.ЗаписьЖурналаРегистрацииОбменаДанными(Сообщение, СтруктураНастроекОбмена, Истина);
		
		Возврат Результат;
	КонецПопытки;
	
	ШаблонИмениФайлаСообщения = ОбменДаннымиСервер.ШаблонИмениФайлаСообщения(СтруктураНастроекОбмена.ТекущийУзелПланаОбмена,
		СтруктураНастроекОбмена.УзелИнформационнойБазы, Ложь);
	
	ИмяФайлаСообщенияОбмена = ОбщегоНазначенияКлиентСервер.ПолучитьПолноеИмяФайла(ИмяКаталогаСообщенияОбмена, ШаблонИмениФайлаСообщения + ".xml");
	
	ПереместитьФайл(ИмяФайлаИзСервисаПередачиФайлов, ИмяФайлаСообщенияОбмена);
	
	ФайлСообщенияОбмена = Новый Файл(ИмяФайлаСообщенияОбмена);
	Если ФайлСообщенияОбмена.Существует() Тогда
		ДатаФайлаСообщенияОбмена = ФайлСообщенияОбмена.ПолучитьВремяИзменения();
	КонецЕсли;
	
	Результат.ИмяВременногоКаталогаСообщенийОбмена = ИмяКаталогаСообщенияОбмена;
	Результат.ИмяФайлаСообщенияОбмена              = ИмяФайлаСообщенияОбмена;
	Результат.ИдентификаторФайлаПакетаДанных       = ДатаФайлаСообщенияОбмена;
	
	Возврат Результат;
КонецФункции

// Получает сообщение обмена из базы-корреспондента через веб-сервис.
// Сохраняет полученное сообщение обмена во временный каталог.
// Используется в том случае, если получение сообщения обмена выполнялось в контексте фонового задания в
// базе-корреспонденте.
//
// Параметры:
//  Отказ                   - Булево - флаг отказа; поднимается в случае возникновения ошибки.
//  УзелИнформационнойБазы  - ПланОбменаСсылка - узел плана обмена, для которого выполняется получение сообщения обмена.
//  ИдентификаторФайла      - УникальныйИдентификатор - идентификатор файла.
//  ПараметрыАутентификации - Структура - содержит параметры аутентификации на веб-сервисе (Пользователь, Пароль).
//
//  Возвращаемое значение:
//   Структура со следующими ключи:
//     * ИмяВременногоКаталогаСообщенийОбмена - полное имя каталога обмена, в которое было загружено сообщение обмена.
//     * ИмяФайлаСообщенияОбмена              - полное имя файла сообщения обмена.
//     * ИдентификаторФайлаПакетаДанных       - дата изменения файла сообщения обмена.
//
Функция ПолучитьСообщениеОбменаВоВременныйКаталогИзИнформационнойБазыКорреспондентаЧерезВебСервисЗавершениеДлительнойОперации(
							Отказ,
							УзелИнформационнойБазы,
							ИдентификаторФайла,
							Знач ПараметрыАутентификации = Неопределено) Экспорт
	
	// Возвращаемое значение функции.
	Результат = Новый Структура;
	Результат.Вставить("ИмяВременногоКаталогаСообщенийОбмена", "");
	Результат.Вставить("ИмяФайлаСообщенияОбмена",              "");
	Результат.Вставить("ИдентификаторФайлаПакетаДанных",       Неопределено);
	
	// Параметры, которые будут определены в функции.
	ИмяКаталогаСообщенияОбмена = "";
	ИмяФайлаСообщенияОбмена = "";
	ДатаФайлаСообщенияОбмена = Дата('00010101');
	
	Попытка
		
		ИмяФайлаИзСервисаПередачиФайлов = ПолучитьФайлИзХранилищаВСервисе(Новый УникальныйИдентификатор(ИдентификаторФайла), УзелИнформационнойБазы,, ПараметрыАутентификации);
		
	Исключение
		
		Отказ = Истина;
		Сообщение = НСтр("ru = 'Возникли ошибки при получении сообщения обмена из сервиса передачи файлов: %1'", ОбщегоНазначения.КодОсновногоЯзыка());
		Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(Сообщение,
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		СтруктураНастроекОбмена = Новый Структура("КлючСообщенияЖурналаРегистрации");
		СтруктураНастроекОбмена.КлючСообщенияЖурналаРегистрации = 
			ОбменДаннымиСервер.КлючСообщенияЖурналаРегистрации(УзелИнформационнойБазы, Перечисления.ДействияПриОбмене.ЗагрузкаДанных);
		ОбменДаннымиСервер.ЗаписьЖурналаРегистрацииОбменаДанными(Сообщение, СтруктураНастроекОбмена, Истина);
		
		Возврат Результат;
		
	КонецПопытки;
	
	Попытка
		ИмяКаталогаСообщенияОбмена = ОбменДаннымиСервер.СоздатьВременныйКаталогСообщенийОбмена();
	Исключение
		Отказ = Истина;
		Сообщение = НСтр("ru = 'При получении сообщения обмена возникли ошибки: %1'", ОбщегоНазначения.КодОсновногоЯзыка());
		Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(Сообщение,
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		СтруктураНастроекОбмена = Новый Структура("КлючСообщенияЖурналаРегистрации");
		СтруктураНастроекОбмена.КлючСообщенияЖурналаРегистрации = 
			ОбменДаннымиСервер.КлючСообщенияЖурналаРегистрации(УзелИнформационнойБазы, Перечисления.ДействияПриОбмене.ЗагрузкаДанных);
		ОбменДаннымиСервер.ЗаписьЖурналаРегистрацииОбменаДанными(Сообщение, СтруктураНастроекОбмена, Истина);
		
		Возврат Результат;
	КонецПопытки;
	
	ИмяПланаОбмена = ОбменДаннымиПовтИсп.ПолучитьИмяПланаОбмена(УзелИнформационнойБазы);
	ТекущийУзелПланаОбмена = ОбменДаннымиПовтИсп.ПолучитьЭтотУзелПланаОбмена(ИмяПланаОбмена);
	
	ШаблонИмениФайлаСообщения = ОбменДаннымиСервер.ШаблонИмениФайлаСообщения(ТекущийУзелПланаОбмена, УзелИнформационнойБазы, Ложь);
	
	ИмяФайлаСообщенияОбмена = ОбщегоНазначенияКлиентСервер.ПолучитьПолноеИмяФайла(ИмяКаталогаСообщенияОбмена, ШаблонИмениФайлаСообщения + ".xml");
	ФайлСообщенияОбмена = Новый Файл(ИмяФайлаСообщенияОбмена);
	Если НЕ ФайлСообщенияОбмена.Существует() Тогда
		// Возможно, файл удастся получить если применить виртуальный код узла.
		ШаблонИмениФайлаСообщенияСтарый = ШаблонИмениФайлаСообщения;
		ШаблонИмениФайлаСообщения = ОбменДаннымиСервер.ШаблонИмениФайлаСообщения(ТекущийУзелПланаОбмена, УзелИнформационнойБазы, Ложь,, Истина);
		Если ШаблонИмениФайлаСообщения <> ШаблонИмениФайлаСообщенияСтарый Тогда
			ИмяФайлаСообщенияОбмена = ОбщегоНазначенияКлиентСервер.ПолучитьПолноеИмяФайла(ИмяКаталогаСообщенияОбмена, ШаблонИмениФайлаСообщения + ".xml");
			ФайлСообщенияОбмена = Новый Файл(ИмяФайлаСообщенияОбмена);
		КонецЕсли;
	КонецЕсли;
	
	ПереместитьФайл(ИмяФайлаИзСервисаПередачиФайлов, ИмяФайлаСообщенияОбмена);
	
	Если ФайлСообщенияОбмена.Существует() Тогда
		ДатаФайлаСообщенияОбмена = ФайлСообщенияОбмена.ПолучитьВремяИзменения();
	КонецЕсли;
	
	Результат.ИмяВременногоКаталогаСообщенийОбмена = ИмяКаталогаСообщенияОбмена;
	Результат.ИмяФайлаСообщенияОбмена              = ИмяФайлаСообщенияОбмена;
	Результат.ИдентификаторФайлаПакетаДанных       = ДатаФайлаСообщенияОбмена;
	
	Возврат Результат;
КонецФункции

Процедура ВыполнитьДействиеОбменаДляУзлаИнформационнойБазыЧерезWebСервис(Отказ,
		УзелИнформационнойБазы, ДействиеПриОбмене, ПараметрыОбмена) Экспорт
	
	ТолькоПараметры = ПараметрыОбмена.ТолькоПараметры;
	
	УстановитьПривилегированныйРежим(Истина);
	
	// ИНИЦИАЛИЗАЦИЯ ОБМЕНА ДАННЫМИ
	СтруктураНастроекОбмена = ОбменДаннымиСервер.НастройкиОбменаДляУзлаИнформационнойБазы(
		УзелИнформационнойБазы, ДействиеПриОбмене, Перечисления.ВидыТранспортаСообщенийОбмена.WS, Ложь);
	ОбменДаннымиСервер.ЗафиксироватьНачалоОбменаВРегистреСведений(СтруктураНастроекОбмена);
	
	Если СтруктураНастроекОбмена.Отказ Тогда
		// Если настройка содержит ошибки, то обмен не производим; статус "Отменено".
		ОбменДаннымиСервер.ЗафиксироватьЗавершениеОбмена(СтруктураНастроекОбмена);
		Отказ = Истина;
		Возврат;
	КонецЕсли;
	
	СтруктураНастроекОбмена.РезультатВыполненияОбмена = Неопределено;
	
	СтрокаСообщения = НСтр("ru = 'Начало процесса обмена данными для узла %1'", ОбщегоНазначения.КодОсновногоЯзыка());
	СтрокаСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(СтрокаСообщения, СтруктураНастроекОбмена.УзелИнформационнойБазыНаименование);
	ОбменДаннымиСервер.ЗаписьЖурналаРегистрацииОбменаДанными(СтрокаСообщения, СтруктураНастроекОбмена);
	
	Если СтруктураНастроекОбмена.ПроизводитьЗагрузкуДанных Тогда
				
		// {Обработчик: ПередЧтениемСообщенияОбмена} Начало
		ФайлСообщенияОбмена = "";
		СтандартнаяОбработка = Истина;
		
		ОбменДаннымиСервер.ПередЧтениемСообщенияОбмена(СтруктураНастроекОбмена.УзелИнформационнойБазы, ФайлСообщенияОбмена, СтандартнаяОбработка);
		// {Обработчик: ПередЧтениемСообщенияОбмена} Окончание
		
		Если СтандартнаяОбработка Тогда
			
			Прокси = Неопределено;
			
			ПараметрыПрокси = Новый Структура;
			ПараметрыПрокси.Вставить("ПараметрыАутентификации", ПараметрыОбмена.ПараметрыАутентификации);
			
			СостояниеНастройки = Неопределено;
			СообщениеОбОшибке  = "";
			ИнициализироватьWSПроксиДляУправленияОбменомДанными(Прокси,
				СтруктураНастроекОбмена, ПараметрыПрокси, Отказ, СостояниеНастройки, СообщениеОбОшибке);

			Если Отказ Тогда
				ОбменДаннымиСервер.ЗаписьЖурналаРегистрацииОбменаДанными(СообщениеОбОшибке, СтруктураНастроекОбмена, Истина);
				СтруктураНастроекОбмена.РезультатВыполненияОбмена = Перечисления.РезультатыВыполненияОбмена.Отменено;
				ОбменДаннымиСервер.ЗафиксироватьЗавершениеОбмена(СтруктураНастроекОбмена);
				Возврат;
			КонецЕсли;
			
			ФайлСообщенияОбмена = "";
			
			Попытка
				
				ВыполнитьВыгрузкуДанных(Прокси, ПараметрыПрокси.ТекущаяВерсия, СтруктураНастроекОбмена, ПараметрыОбмена);
				
				Если ПараметрыОбмена.ДлительнаяОперация Тогда
					
					ОжиданиеЗавершенияОперации(СтруктураНастроекОбмена, ПараметрыОбмена, Прокси, ПараметрыПрокси, Перечисления.ДействияПриОбмене.ЗагрузкаДанных);
					
				КонецЕсли;
				
				УИДФайлаСообщения = Новый УникальныйИдентификатор(ПараметрыОбмена.ИдентификаторФайла);
				ФайлСообщенияОбмена = ПолучитьФайлИзХранилищаВСервисе(УИДФайлаСообщения, УзелИнформационнойБазы, 1024, ПараметрыОбмена.ПараметрыАутентификации);
				
			Исключение
				
				ОбменДаннымиСервер.ЗаписьЖурналаРегистрацииОбменаДанными(
					ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),СтруктураНастроекОбмена, Истина);
				СтруктураНастроекОбмена.РезультатВыполненияОбмена = Перечисления.РезультатыВыполненияОбмена.Ошибка;
				Отказ = Истина;
				
			КонецПопытки;
			
		КонецЕсли;
		
		Если Не Отказ Тогда
			
			ОбменДаннымиСервер.ПрочитатьСообщениеСИзменениямиДляУзла(СтруктураНастроекОбмена, ФайлСообщенияОбмена,, ТолькоПараметры);
			
		КонецЕсли;
		
		// {Обработчик: ПослеЧтенияСообщенияОбмена} Начало
		СтандартнаяОбработка = Истина;
		
		ОбменДаннымиСервер.ПослеЧтенияСообщенияОбмена(
					СтруктураНастроекОбмена.УзелИнформационнойБазы,
					ФайлСообщенияОбмена,
					ОбменДаннымиСервер.РезультатВыполненияОбменаВыполнено(СтруктураНастроекОбмена.РезультатВыполненияОбмена),
					СтандартнаяОбработка,
					Не ТолькоПараметры);
		// {Обработчик: ПослеЧтенияСообщенияОбмена} Окончание
		
		Если СтандартнаяОбработка Тогда
			
			Попытка
				Если Не ПустаяСтрока(ФайлСообщенияОбмена) 
					И ТипЗнч(ОбменДаннымиСервер.СообщениеОбменаДаннымиИзГлавногоУзла()) <> Тип("Структура") Тогда
					УдалитьФайлы(ФайлСообщенияОбмена);
				КонецЕсли;
			Исключение
				ЗаписьЖурналаРегистрации(ОбменДаннымиСервер.СобытиеЖурналаРегистрацииОбменДанными(),
					УровеньЖурналаРегистрации.Ошибка,,, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
			КонецПопытки;
			
		КонецЕсли;
					
	ИначеЕсли СтруктураНастроекОбмена.ПроизводитьВыгрузкуДанных Тогда
		
		Прокси = Неопределено;
		
		ПараметрыПрокси = Новый Структура;
		ПараметрыПрокси.Вставить("ПараметрыАутентификации", ПараметрыОбмена.ПараметрыАутентификации);
		Если ПараметрыОбмена.СообщениеДляСопоставленияДанных Тогда
			ПараметрыПрокси.Вставить("МинимальнаяВерсия", "3.0.1.1");
		КонецЕсли;
		
		СостояниеНастройки = Неопределено;
		СообщениеОбОшибке  = "";
		ИнициализироватьWSПроксиДляУправленияОбменомДанными(Прокси,
			СтруктураНастроекОбмена, ПараметрыПрокси, Отказ, СостояниеНастройки, СообщениеОбОшибке);
		
		Если Отказ Тогда
			ОбменДаннымиСервер.ЗаписьЖурналаРегистрацииОбменаДанными(СообщениеОбОшибке, СтруктураНастроекОбмена, Истина);
			СтруктураНастроекОбмена.РезультатВыполненияОбмена = Перечисления.РезультатыВыполненияОбмена.Отменено;
			ОбменДаннымиСервер.ЗафиксироватьЗавершениеОбмена(СтруктураНастроекОбмена);
			Возврат;
		КонецЕсли;
		
		ВременныйКаталог = ПолучитьИмяВременногоФайла();
		СоздатьКаталог(ВременныйКаталог);
		
		ФайлСообщенияОбмена = ОбщегоНазначенияКлиентСервер.ПолучитьПолноеИмяФайла(
			ВременныйКаталог, ОбменДаннымиСервер.УникальноеИмяФайлаСообщенияОбмена());
		
		Попытка
			ОбменДаннымиСервер.ЗаписатьСообщениеСИзменениямиДляУзла(СтруктураНастроекОбмена, ФайлСообщенияОбмена);
		Исключение
			ОбменДаннымиСервер.ЗаписьЖурналаРегистрацииОбменаДанными(
				ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()), СтруктураНастроекОбмена, Истина);
			СтруктураНастроекОбмена.РезультатВыполненияОбмена = Перечисления.РезультатыВыполненияОбмена.Ошибка;
			Отказ = Истина;
		КонецПопытки;
		
		// Отправка сообщения обмена только в случае успешной выгрузки данных.
		Если ОбменДаннымиСервер.РезультатВыполненияОбменаВыполнено(СтруктураНастроекОбмена.РезультатВыполненияОбмена) И Не Отказ Тогда
			
			Попытка
				
				ИдентификаторФайлаУИД = ПоместитьФайлВХранилищеВСервисе(Прокси, ПараметрыПрокси.ТекущаяВерсия,
					СтруктураНастроекОбмена, ФайлСообщенияОбмена, УзелИнформационнойБазы, 1024);
				
				ИдентификаторФайлаСтрокой = Строка(ИдентификаторФайлаУИД);
				
				Попытка
					УдалитьФайлы(ВременныйКаталог);
				Исключение
					ЗаписьЖурналаРегистрации(ОбменДаннымиСервер.СобытиеЖурналаРегистрацииОбменДанными(),
						УровеньЖурналаРегистрации.Ошибка,,, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
				КонецПопытки;
					
				Если ПараметрыОбмена.СообщениеДляСопоставленияДанных
					И (СостояниеНастройки.ПоддерживаетсяСопоставлениеДанных
						Или Не СостояниеНастройки.НастройкаСинхронизацииДанныхЗавершена) Тогда
					
					ПоместитьСообщениеДляСопоставленияДанных(Прокси, ПараметрыПрокси.ТекущаяВерсия,
						СтруктураНастроекОбмена, ИдентификаторФайлаСтрокой);
				
				Иначе
					
					ВыполнитьЗагрузкуДанных(Прокси, ПараметрыПрокси.ТекущаяВерсия,
						СтруктураНастроекОбмена, ПараметрыОбмена, ИдентификаторФайлаСтрокой);
						
					Если ПараметрыОбмена.ДлительнаяОперация Тогда
						
						ОжиданиеЗавершенияОперации(СтруктураНастроекОбмена, ПараметрыОбмена, Прокси, ПараметрыПрокси, Перечисления.ДействияПриОбмене.ВыгрузкаДанных);
						
					КонецЕсли;
					
				КонецЕсли;
				
			Исключение
				
				ОбменДаннымиСервер.ЗаписьЖурналаРегистрацииОбменаДанными(
					ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()), СтруктураНастроекОбмена, Истина);
				СтруктураНастроекОбмена.РезультатВыполненияОбмена = Перечисления.РезультатыВыполненияОбмена.Ошибка;
				Отказ = Истина;
				
			КонецПопытки;
			
		КонецЕсли;
		
		Попытка
			УдалитьФайлы(ВременныйКаталог);
		Исключение
			ЗаписьЖурналаРегистрации(ОбменДаннымиСервер.СобытиеЖурналаРегистрацииОбменДанными(),
				УровеньЖурналаРегистрации.Ошибка,,, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		КонецПопытки;
			
	КонецЕсли;
	
	ОбменДаннымиСервер.ЗафиксироватьЗавершениеОбмена(СтруктураНастроекОбмена);
	
	Если Не ОбменДаннымиСервер.РезультатВыполненияОбменаВыполнено(СтруктураНастроекОбмена.РезультатВыполненияОбмена) Тогда
		Отказ = Истина;
	КонецЕсли;
	
КонецПроцедуры

// Выполняет получение файла сообщения обмена из базы-корреспондента через веб-сервис.
// Выполняет загрузку полученного файла сообщения обмена в эту базу.
//
// Параметры:
//  Отказ                   - Булево - флаг отказа; поднимается в случае возникновения ошибки.
//  УзелИнформационнойБазы  - ПланОбменаСсылка - узел плана обмена, для которого выполняется получение сообщения обмена.
//  ИдентификаторФайла      - УникальныйИдентификатор - идентификатор файла.
//  ДатаНачалаОперации      - Дата - дата начала загрузки.
//  ПараметрыАутентификации - Структура - содержит параметры аутентификации на веб-сервисе (Пользователь, Пароль).
//
Процедура ВыполнитьОбменДаннымиДляУзлаИнформационнойБазыЗавершениеДлительнойОперации(
															Отказ,
															Знач УзелИнформационнойБазы,
															Знач ИдентификаторФайла,
															Знач ДатаНачалаОперации,
															Знач ПараметрыАутентификации = Неопределено,
															ВыдаватьОшибку = Ложь) Экспорт
	
	ОбменДаннымиСервер.ПроверитьВозможностьВыполненияОбменов();
	
	ОбменДаннымиСервер.ПроверитьИспользованиеОбменаДанными();
	
	УстановитьПривилегированныйРежим(Истина);
	
	Попытка
		ФайлСообщенияОбмена = ПолучитьФайлИзХранилищаВСервисе(Новый УникальныйИдентификатор(ИдентификаторФайла),
			УзелИнформационнойБазы,, ПараметрыАутентификации);
	Исключение
		ОбменДаннымиСервер.ЗафиксироватьЗавершениеОбменаСОшибкой(УзелИнформационнойБазы,
			Перечисления.ДействияПриОбмене.ЗагрузкаДанных,
			ДатаНачалаОперации,
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		Если ВыдаватьОшибку Тогда
			ВызватьИсключение;
		Иначе
			Отказ = Истина;
		КонецЕсли;
		Возврат;
	КонецПопытки;
	
	// Загрузка файла сообщения обмена в эту базу.
	ПараметрыОбменаДанными = ОбменДаннымиСервер.ПараметрыОбменаДаннымиЧерезФайлИлиСтроку();
	
	ПараметрыОбменаДанными.УзелИнформационнойБазы        = УзелИнформационнойБазы;
	ПараметрыОбменаДанными.ПолноеИмяФайлаСообщенияОбмена = ФайлСообщенияОбмена;
	ПараметрыОбменаДанными.ДействиеПриОбмене             = Перечисления.ДействияПриОбмене.ЗагрузкаДанных;
	ПараметрыОбменаДанными.ДатаНачалаОперации            = ДатаНачалаОперации;
	
	Попытка
		ОбменДаннымиСервер.ВыполнитьОбменДаннымиДляУзлаИнформационнойБазыЧерезФайлИлиСтроку(ПараметрыОбменаДанными);
	Исключение
		ОбменДаннымиСервер.ЗафиксироватьЗавершениеОбменаСОшибкой(УзелИнформационнойБазы,
			Перечисления.ДействияПриОбмене.ЗагрузкаДанных,
			ДатаНачалаОперации,
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		Если ВыдаватьОшибку Тогда
			ВызватьИсключение;
		Иначе
			Отказ = Истина;
		КонецЕсли;
	КонецПопытки;
	
	Попытка
		УдалитьФайлы(ФайлСообщенияОбмена);
	Исключение
		ЗаписьЖурналаРегистрации(ОбменДаннымиСервер.СобытиеЖурналаРегистрацииОбменДанными(),
			УровеньЖурналаРегистрации.Ошибка,,, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
	КонецПопытки;
	
КонецПроцедуры

// Функция по переданному идентификатору скачивает файл из сервиса передачи файлов.
//
// Параметры:
//  ИдентификаторФайла       - УникальныйИдентификатор - идентификатор получаемого файла.
//  УзелИнформационнойБазы   - ПланОбменаСсылка - узел плана обмена, для которого необходимо получить файл.
//  РазмерЧасти              - Число - размер части в килобайтах. Если значение равно 0,
//                             то разбивка на части не производится.
//  ПараметрыАутентификации  - Структура: АдресСервиса, ИмяПользователя, ПарольПользователя.
//
// Возвращаемое значение:
//  Строка - путь к полученному файлу.
//
Функция ПолучитьФайлИзХранилищаВСервисе(Знач ИдентификаторФайла, Знач УзелИнформационнойБазы,
	Знач РазмерЧасти = 1024, Знач ПараметрыАутентификации = Неопределено) Экспорт
	
	// Возвращаемое значение функции.
	ИмяФайлаРезультата = "";
	
	ДополнительныеПараметры = Новый Структура("ПараметрыАутентификации", ПараметрыАутентификации);
	
	СообщениеОбОшибке = "";
	Прокси = WSПроксиДляУзлаИнформационнойБазы(УзелИнформационнойБазы, СообщениеОбОшибке, ДополнительныеПараметры);
	
	Если Прокси = Неопределено Тогда
		ВызватьИсключение СообщениеОбОшибке;
	КонецЕсли;
	
	ИдентификаторСессии = Неопределено;
	КоличествоЧастей    = Неопределено;
	
	ПараметрыПрокси = Новый Структура("ТекущаяВерсия", ДополнительныеПараметры.ТекущаяВерсия);
	СтруктураНастроекОбмена = ОбменДаннымиСервер.НастройкиОбменаДляУзлаИнформационнойБазы(УзелИнформационнойБазы, 
		Перечисления.ДействияПриОбмене.ВыгрузкаДанных, Перечисления.ВидыТранспортаСообщенийОбмена.WS, Ложь);

	ПодготовитьФайлДляПолучения(Прокси, ПараметрыПрокси.ТекущаяВерсия, СтруктураНастроекОбмена,
		ИдентификаторФайла, РазмерЧасти, ИдентификаторСессии, КоличествоЧастей);
	
	ИменаФайлов = Новый Массив;
	
	КаталогСборки = ПолучитьИмяВременногоФайла();
	СоздатьКаталог(КаталогСборки);
	
	ШаблонИмениФайла = "data.zip.[n]";
	
	// Протоколирование событий обмена.
	СтруктураНастроекОбмена.КлючСообщенияЖурналаРегистрации = 
		ОбменДаннымиСервер.КлючСообщенияЖурналаРегистрации(УзелИнформационнойБазы, Перечисления.ДействияПриОбмене.ЗагрузкаДанных);
	
	Комментарий = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Начало получения сообщения обмена из Интернета (количество частей файла %1).'"),
		Формат(КоличествоЧастей, "ЧН=0; ЧГ=0"));
	ОбменДаннымиСервер.ЗаписьЖурналаРегистрацииОбменаДанными(Комментарий, СтруктураНастроекОбмена);
	
	Для НомерЧасти = 1 По КоличествоЧастей Цикл
		ДанныеЧасти = Неопределено; // ДвоичныеДанные
		Попытка
			ПолучитьЧастьФайла(Прокси, ПараметрыПрокси.ТекущаяВерсия, СтруктураНастроекОбмена, ИдентификаторСессии, НомерЧасти, ДанныеЧасти);
		Исключение
			Прокси.ReleaseFile(ИдентификаторСессии);
			ВызватьИсключение;
		КонецПопытки;
		
		ИмяФайла = СтрЗаменить(ШаблонИмениФайла, "[n]", Формат(НомерЧасти, "ЧГ=0"));
		ИмяФайлаЧасти = ОбщегоНазначенияКлиентСервер.ПолучитьПолноеИмяФайла(КаталогСборки, ИмяФайла);
		
		ДанныеЧасти.Записать(ИмяФайлаЧасти);
		ИменаФайлов.Добавить(ИмяФайлаЧасти);
	КонецЦикла;
	ДанныеЧасти = Неопределено;
	
	Прокси.ReleaseFile(ИдентификаторСессии);
	
	ИмяАрхива = ОбщегоНазначенияКлиентСервер.ПолучитьПолноеИмяФайла(КаталогСборки, "data.zip");
	
	ОбъединитьФайлы(ИменаФайлов, ИмяАрхива);
	
	РегистрыСведений.АрхивСообщенийОбменов.ПоместитьСообщениеВАрхив(УзелИнформационнойБазы, ИмяАрхива);
	
	Разархиватор = Новый ЧтениеZipФайла(ИмяАрхива);
	Если Разархиватор.Элементы.Количество() = 0 Тогда
		Попытка
			УдалитьФайлы(КаталогСборки);
		Исключение
			ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрацииУдалениеВременногоФайла(),
				УровеньЖурналаРегистрации.Ошибка,,, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		КонецПопытки;
		ВызватьИсключение(НСтр("ru = 'Файл архива не содержит данных.'"));
	КонецЕсли;
	
	// Протоколирование событий обмена.
	ФайлАрхива = Новый Файл(ИмяАрхива);
	
	Комментарий = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Окончание получения сообщения обмена из Интернета (размер сжатого сообщения обмена %1 Мб).'"),
		Формат(Окр(ФайлАрхива.Размер() / 1024 / 1024, 3), "ЧН=0; ЧГ=0"));
	ОбменДаннымиСервер.ЗаписьЖурналаРегистрацииОбменаДанными(Комментарий, СтруктураНастроекОбмена);
	
	ЭлементАрхива = Разархиватор.Элементы.Получить(0);
	ИмяФайла = ОбщегоНазначенияКлиентСервер.ПолучитьПолноеИмяФайла(КаталогСборки, ЭлементАрхива.Имя);
	
	Разархиватор.Извлечь(ЭлементАрхива, КаталогСборки);
	Разархиватор.Закрыть();
	
	Файл = Новый Файл(ИмяФайла);
	
	ВременныйКаталог = ПолучитьИмяВременногоФайла(); //АПК:441 удаление каталога происходит при получении данных обмена в другой ИБ
	СоздатьКаталог(ВременныйКаталог);
	
	ИмяФайлаРезультата = ОбщегоНазначенияКлиентСервер.ПолучитьПолноеИмяФайла(ВременныйКаталог, Файл.Имя);
	
	ПереместитьФайл(ИмяФайла, ИмяФайлаРезультата);
	
	Попытка
		УдалитьФайлы(КаталогСборки);
	Исключение
		ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрацииУдалениеВременногоФайла(),
			УровеньЖурналаРегистрации.Ошибка,,, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
	КонецПопытки;
		
	Возврат ИмяФайлаРезультата;
КонецФункции

// Функция передает указанный файл в сервис передачи файлов.
//
// Параметры:
//  Прокси
//  ВерсияПрокси             - Строка - версия используемого веб-сервиса
//  СтруктураНастроекОбмена  - Структура - структура со всеми необходимыми данными и объектами для выполнения обмена.
//  ИмяФайла                 - Строка - путь к передаваемому файлу.
//  УзелИнформационнойБазы   - ПланОбменаСсылка - узел плана обмена, для которого необходимо получить файл. 
//  РазмерЧастиКБ            - Число - размер части в килобайтах. Если значение равно 0,
//                             то разбивка на части не производится.
//  ИдентификаторФайла       - УникальныйИдентификатор - идентификатор помещаемого в сервис файла.
//
// Возвращаемое значение:
//  УникальныйИдентификатор  - идентификатор файла в сервисе передачи файлов.
//
Функция ПоместитьФайлВХранилищеВСервисе(Прокси, ВерсияПрокси, СтруктураНастроекОбмена, Знач ИмяФайла, 
	Знач УзелИнформационнойБазы, Знач РазмерЧастиКБ = 1024, ИдентификаторФайла = Неопределено) Экспорт
	
	Если Прокси = Неопределено Тогда
		
		ВызватьИсключение НСтр("ru ='Не определен WS-прокси передачи файла выгрузки в базу приемник. 
			|Обратитесь к администратору.'", ОбщегоНазначения.КодОсновногоЯзыка());
		
	КонецЕсли;
	
	КаталогФайлов = ПолучитьИмяВременногоФайла();
	СоздатьКаталог(КаталогФайлов);
	
	// Архивирование файла.
	ИмяНеразделенногоФайла = ОбщегоНазначенияКлиентСервер.ПолучитьПолноеИмяФайла(КаталогФайлов, "data.zip");
	Архиватор = Новый ЗаписьZipФайла(ИмяНеразделенногоФайла,,,, УровеньСжатияZIP.Максимальный);
	Архиватор.Добавить(ИмяФайла);
	Архиватор.Записать();
	
	// Разделение файла на части.
	ИдентификаторСессии = Новый УникальныйИдентификатор;
	
	РазмерЧастиВБайтах = РазмерЧастиКБ * 1024;
	ИменаФайлов = РазделитьФайл(ИмяНеразделенногоФайла, РазмерЧастиВБайтах);
	
	КоличествоЧастей = ИменаФайлов.Количество();
	Для НомерЧасти = 1 По КоличествоЧастей Цикл
		
		ИмяФайлаЧасти = ИменаФайлов[НомерЧасти - 1];
		ДанныеФайла = Новый ДвоичныеДанные(ИмяФайлаЧасти);
		ПоместитьЧастьФайла(Прокси, ВерсияПрокси, СтруктураНастроекОбмена, ИдентификаторСессии, НомерЧасти, ДанныеФайла);
		
	КонецЦикла;
	
	Попытка
		УдалитьФайлы(КаталогФайлов);
	Исключение
		ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрацииУдалениеВременногоФайла(),
			УровеньЖурналаРегистрации.Ошибка,,, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
	КонецПопытки;
	
	СобратьФайлИзЧастей(Прокси, ВерсияПрокси, СтруктураНастроекОбмена, ИдентификаторСессии, КоличествоЧастей, ИдентификаторФайла);
	
	Возврат ИдентификаторФайла;
	
КонецФункции

// Инициализирует WS-прокси для выполнения управляющих команд обмена данными,
// предварительно проверяет наличие узла обмена.
//
// Параметры:
//   Прокси - WSПрокси - WS-прокси для передачи управляющих команд.
//   СтруктураНастроек - Структура - структура параметров для подключения к корреспонденту и идентификации настройки обмена:
//     * ИмяПланаОбмена - Строка - имя плана обмена, используемого при синхронизации.
//     * УзелИнформационнойБазы - ПланОбменаСсылка - узел плана обмена, соответствующий корреспонденту.
//     * КлючСообщенияЖурналаРегистрации - Строка - имя события для записи ошибок в журнал регистрации.
//     * ТекущийУзелПланаОбмена - ПланОбменаСсылка - ссылка на ЭтотУзел плана обмена.
//     * ТекущийУзелПланаОбменаКод - Строка - идентификатор текущего узла плана обмена.
//     * ДействиеПриОбмене - ПеречислениеСсылка.ДействияПриОбмене - указывает на направление обмена.
//   ПараметрыПрокси - Структура:
//     * ПараметрыАутентификации - Строка
//                               - Структура - содержит пароль для аутентификации на веб-сервере.
//     * СтруктураНастроекАутентификации - Структура - содержит структуру настроек для аутентификации на веб-сервере.
//     * МинимальнаяВерсия - Строка - номер минимальной версии интерфейса "ОбменДанными", требуемый для выполнения действий.
//     * ТекущаяВерсия - Строка - исходящий, фактическая версия интерфейса инициализированного WS-прокси.
//   Отказ - Булево - признак неуспешной инициализации WS-прокси.
//   СостояниеНастройки - Структура - исходящий, возвращает состояние настройки синхронизации, описанной в СтруктураНастроек:
//     * НастройкаСуществует - Булево - Истина, если настройка с указанными планом обмена и идентификатором узла существует.
//     * НастройкаСинхронизацииДанныхЗавершена - Булево - Истина, если настройка синхронизации завершена.
//     * ПоддерживаетсяСопоставлениеДанных - Булево - Истина, если корреспондент поддерживает функцию сопоставления данных.
//     * ПолученоСообщениеДляСопоставленияДанных - Булево - Истина, в корреспондент загружено сообщение для сопоставления.
//   СтрокаСообщенияОбОшибке - Строка - описание ошибки инициализации WS-прокси.
//
Процедура ИнициализироватьWSПроксиДляУправленияОбменомДанными(Прокси,
		СтруктураНастроек, ПараметрыПрокси, Отказ, СостояниеНастройки, СтрокаСообщенияОбОшибке = "") Экспорт
	
	МинимальнаяВерсия = "0.0.0.0";
	Если ПараметрыПрокси.Свойство("МинимальнаяВерсия") Тогда
		МинимальнаяВерсия = ПараметрыПрокси.МинимальнаяВерсия;
	КонецЕсли;
	
	ПараметрыАутентификации = Неопределено;
	ПараметрыПрокси.Свойство("ПараметрыАутентификации", ПараметрыАутентификации);
	
	СтруктураНастроекАутентификации = Неопределено;
	ПараметрыПрокси.Свойство("СтруктураНастроекАутентификации", СтруктураНастроекАутентификации);
	
	ПараметрыПрокси.Вставить("ТекущаяВерсия", Неопределено);
	
	ДополнительныеПараметры = Новый Структура;
	ДополнительныеПараметры.Вставить("ПараметрыАутентификации",         ПараметрыАутентификации);
	ДополнительныеПараметры.Вставить("МинимальнаяВерсия",               МинимальнаяВерсия);
	ДополнительныеПараметры.Вставить("СтруктураНастроекАутентификации", СтруктураНастроекАутентификации);
	
	Прокси = WSПроксиДляУзлаИнформационнойБазы(
		СтруктураНастроек.УзелИнформационнойБазы,
		СтрокаСообщенияОбОшибке,
		ДополнительныеПараметры);
		
	Если Прокси = Неопределено Тогда
		Отказ = Истина;
		Возврат;
	КонецЕсли;
	
	ПараметрыПрокси.ТекущаяВерсия = ДополнительныеПараметры.ТекущаяВерсия;
	
	Если ОбменДаннымиСервер.ЭтоПланОбменаXDTO(СтруктураНастроек.ИмяПланаОбмена) Тогда
		
		ПсевдонимУзла = ОбменДаннымиСервер.ПсевдонимПредопределенногоУзла(СтруктураНастроек.УзелИнформационнойБазы);
		Если ЗначениеЗаполнено(ПсевдонимУзла) Тогда
			// Проверка настройки со старым идентификатором (префиксом).
			СтруктураНастроекПредопределенного = ОбщегоНазначения.СкопироватьРекурсивно(СтруктураНастроек, Ложь); // Структура
			СтруктураНастроекПредопределенного.Вставить("ТекущийУзелПланаОбменаКод", ПсевдонимУзла);
			СостояниеНастройки = СостояниеНастройкиСинхронизацииВКорреспонденте(Прокси, ПараметрыПрокси, СтруктураНастроекПредопределенного);
				
			Если Не СостояниеНастройки.НастройкаСуществует Тогда
				Если ВКорреспондентеУстаревшийВариантНастроекОбмена(
						Прокси, ПараметрыПрокси, СостояниеНастройки, СтруктураНастроек, ПсевдонимУзла, Отказ, СтрокаСообщенияОбОшибке)
					Или Отказ Тогда
					Возврат;
				КонецЕсли;
			Иначе
				СтруктураНастроек.ТекущийУзелПланаОбменаКод = ПсевдонимУзла;
				Возврат;
			КонецЕсли;
		КонецЕсли;
		
		СостояниеНастройки = СостояниеНастройкиСинхронизацииВКорреспонденте(Прокси, ПараметрыПрокси, СтруктураНастроек);
			
		Если Не СостояниеНастройки.НастройкаСуществует Тогда
			Если ВКорреспондентеУстаревшийВариантНастроекОбмена(
					Прокси, ПараметрыПрокси, СостояниеНастройки, СтруктураНастроек, СтруктураНастроек.ТекущийУзелПланаОбменаКод, Отказ, СтрокаСообщенияОбОшибке)
				Или Отказ Тогда
				Возврат;
			КонецЕсли;
		КонецЕсли;
		
	Иначе
		
		СостояниеНастройки = СостояниеНастройкиСинхронизацииВКорреспонденте(Прокси, ПараметрыПрокси, СтруктураНастроек);
			
	КонецЕсли;
	
	Если Не СостояниеНастройки.НастройкаСуществует Тогда
		СтрокаСообщенияОбОшибке = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Не найдена настройка синхронизации данных ""%1"" с идентификатором ""%2"".'"),
			СтруктураНастроек.ИмяПланаОбмена,
			СтруктураНастроек.ТекущийУзелПланаОбменаКод);
		Отказ = Истина;
	КонецЕсли;
	
КонецПроцедуры

Функция WSПроксиДляУзлаИнформационнойБазы(УзелИнформационнойБазы, СтрокаСообщенияОбОшибке = "", ДополнительныеПараметры = Неопределено) Экспорт
		
	Если ДополнительныеПараметры = Неопределено Тогда
		ДополнительныеПараметры = Новый Структура;
	КонецЕсли;
	
	ПараметрыАутентификации = Неопределено;
	ДополнительныеПараметры.Свойство("ПараметрыАутентификации", ПараметрыАутентификации);
	
	СтруктураНастроекАутентификации = Неопределено;
	ДополнительныеПараметры.Свойство("СтруктураНастроекАутентификации", СтруктураНастроекАутентификации);
	
	МинимальнаяВерсия = Неопределено;
	Если Не ДополнительныеПараметры.Свойство("МинимальнаяВерсия", МинимальнаяВерсия) Тогда
		МинимальнаяВерсия = "0.0.0.0";
	КонецЕсли;
	
	ДополнительныеПараметры.Вставить("ТекущаяВерсия");
		
	Если СтруктураНастроекАутентификации = Неопределено Тогда
		Если ОбменДаннымиПовтИсп.ЭтоУзелОбменаСообщениями(УзелИнформационнойБазы) Тогда
			МодульНастройкиТранспортаОбменаСообщениями = ОбщегоНазначения.ОбщийМодуль("РегистрыСведений.НастройкиТранспортаОбменаСообщениями");
			СтруктураНастроекАутентификации = МодульНастройкиТранспортаОбменаСообщениями.НастройкиТранспортаWS(
				УзелИнформационнойБазы, ПараметрыАутентификации);
		Иначе
			СтруктураНастроекАутентификации = РегистрыСведений.НастройкиТранспортаОбменаДанными.НастройкиТранспортаWS(
				УзелИнформационнойБазы, ПараметрыАутентификации);
		КонецЕсли;
	КонецЕсли;
	
	Попытка
		ВерсииКорреспондента = ОбменДаннымиПовтИсп.ВерсииКорреспондента(СтруктураНастроекАутентификации);
	Исключение
		СтрокаСообщенияОбОшибке = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрацииУстановкаПодключенияКWebСервису(),
			УровеньЖурналаРегистрации.Ошибка,,, СтрокаСообщенияОбОшибке);
		Возврат Неопределено;
	КонецПопытки;
	
	ДоступныеВерсии = Новый Соответствие;
	Для Каждого Версия Из СтрРазделить("3.0.2.2;3.0.2.1;3.0.1.1;2.1.1.7;2.0.1.6", ";", Ложь) Цикл
		ДоступныеВерсии.Вставить(Версия, ВерсииКорреспондента.Найти(Версия) <> Неопределено
			И (ОбщегоНазначенияКлиентСервер.СравнитьВерсии(Версия, МинимальнаяВерсия) >= 0));
	КонецЦикла;
	
	ДоступныеВерсии.Вставить("0.0.0.0", ОбщегоНазначенияКлиентСервер.СравнитьВерсии("0.0.0.0", МинимальнаяВерсия) >= 0);
	
	Если ДоступныеВерсии.Получить("3.0.2.2") = Истина Тогда
		ТекущаяВерсия = "3.0.2.2";
	ИначеЕсли ДоступныеВерсии.Получить("3.0.2.1") = Истина Тогда
		ТекущаяВерсия = "3.0.2.1";
	ИначеЕсли ДоступныеВерсии.Получить("3.0.1.1") = Истина Тогда
		ТекущаяВерсия = "3.0.1.1";
	ИначеЕсли ДоступныеВерсии.Получить("2.1.1.7") = Истина Тогда
		ТекущаяВерсия = "2.1.1.7";
	ИначеЕсли ДоступныеВерсии.Получить("2.0.1.6") = Истина Тогда
		ТекущаяВерсия = "2.0.1.6";
	ИначеЕсли ДоступныеВерсии.Получить("0.0.0.0") = Истина Тогда
		ТекущаяВерсия = "0.0.0.0";
	Иначе
		СтрокаСообщенияОбОшибке = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Корреспондент не поддерживает требуемую версию ""%1"" интерфейса ""ОбменДанными"".'"),
			МинимальнаяВерсия);
		Возврат Неопределено;
	КонецЕсли;

	ДополнительныеПараметры.ТекущаяВерсия = ТекущаяВерсия;
	
	Если ТекущаяВерсия = "0.0.0.0" Тогда
		ВерсияДляАдреса = "";
	Иначе
		ВерсияДляАдреса = "_" + СтрЗаменить(ТекущаяВерсия, ".", "_");		
	КонецЕсли;
	
	//
	ОбменДаннымиСервер.УдалитьНезначащиеСимволыВНастройкахПодключения(СтруктураНастроекАутентификации);
	
	СтруктураНастроекАутентификации.Вставить("WSURLПространстваИменСервиса", "http://www.1c.ru/SSL/Exchange" + ВерсияДляАдреса);
	СтруктураНастроекАутентификации.Вставить("WSИмяСервиса",                 "Exchange" + ВерсияДляАдреса);
	СтруктураНастроекАутентификации.Вставить("WSТаймаут",                    600);
	
	Возврат ПолучитьWSПроксиПоПараметрамПодключения(СтруктураНастроекАутентификации, СтрокаСообщенияОбОшибке, СтрокаСообщенияОбОшибке, Истина);
	
КонецФункции

Функция ПолучитьWSПроксиПоПараметрамПодключения(
					СтруктураНастроек,
					СтрокаСообщенияОбОшибке = "",
					СообщениеПользователю = "",
					ДелатьКонтрольныйВызов = Ложь) Экспорт
	
	Попытка
		ПроверитьКорректностьФорматаАдресаWSПрокси(СтруктураНастроек.WSURLВебСервиса);
	Исключение
		СообщениеПользователю = ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
		СтрокаСообщенияОбОшибке = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрацииУстановкаПодключенияКWebСервису(), УровеньЖурналаРегистрации.Ошибка,,, СтрокаСообщенияОбОшибке);
		Возврат Неопределено;
	КонецПопытки;

	Попытка
		ПроверитьНедопустимыеСимволыВИмениПользователяWSПрокси(СтруктураНастроек.WSИмяПользователя);
	Исключение
		СообщениеПользователю = ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
		СтрокаСообщенияОбОшибке = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрацииУстановкаПодключенияКWebСервису(), УровеньЖурналаРегистрации.Ошибка,,, СтрокаСообщенияОбОшибке);
		Возврат Неопределено;
	КонецПопытки;
	
	МестоположениеWSDL = "[URLВебСервиса]/ws/[ИмяСервиса]?wsdl";
	МестоположениеWSDL = СтрЗаменить(МестоположениеWSDL, "[URLВебСервиса]", СтруктураНастроек.WSURLВебСервиса);
	МестоположениеWSDL = СтрЗаменить(МестоположениеWSDL, "[ИмяСервиса]",    СтруктураНастроек.WSИмяСервиса);
	
	ПараметрыПодключения = ОбщегоНазначения.ПараметрыПодключенияWSПрокси();
	ПараметрыПодключения.АдресWSDL = МестоположениеWSDL;
	ПараметрыПодключения.URIПространстваИмен = СтруктураНастроек.WSURLПространстваИменСервиса;
	ПараметрыПодключения.ИмяСервиса = СтруктураНастроек.WSИмяСервиса;
	ПараметрыПодключения.ИмяПользователя = СтруктураНастроек.WSИмяПользователя; 
	ПараметрыПодключения.Пароль = СтруктураНастроек.WSПароль;
	ПараметрыПодключения.Таймаут = СтруктураНастроек.WSТаймаут;
	ПараметрыПодключения.ДелатьКонтрольныйВызов = ДелатьКонтрольныйВызов;
	
	Попытка
		WSПрокси = ОбщегоНазначения.СоздатьWSПрокси(ПараметрыПодключения);
	Исключение
		СообщениеПользователю = ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
		СтрокаСообщенияОбОшибке = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрацииУстановкаПодключенияКWebСервису(), УровеньЖурналаРегистрации.Ошибка,,, СтрокаСообщенияОбОшибке);
		Возврат Неопределено;
	КонецПопытки;
	
	Возврат WSПрокси;
КонецФункции

Функция ЕстьПодключениеККорреспонденту(Знач Корреспондент,
		Знач СтруктураНастроек,
		СообщениеПользователю = "",
		НастройкаСинхронизацииДанныхЗавершена = Истина,
		ПолученоСообщениеДляСопоставленияДанных = Ложь) Экспорт
		
	СтруктураНастроекОбмена = ОбменДаннымиСервер.НастройкиОбменаДляУзлаИнформационнойБазы(
		Корреспондент, Перечисления.ДействияПриОбмене.ВыгрузкаДанных, Перечисления.ВидыТранспортаСообщенийОбмена.WS, Ложь);
		
	СтруктураНастроекОбмена.Вставить("КлючСообщенияЖурналаРегистрации", 
		НСтр("ru = 'Обмен данными.Проверка подключения'", ОбщегоНазначения.КодОсновногоЯзыка()));

	ПараметрыПрокси = Новый Структура;
	ПараметрыПрокси.Вставить("ПараметрыАутентификации",         Неопределено);
	ПараметрыПрокси.Вставить("СтруктураНастроекАутентификации", СтруктураНастроек);
	
	Прокси = Неопределено;
	СостояниеНастройки = Неопределено;
	Отказ = Ложь;
	ИнициализироватьWSПроксиДляУправленияОбменомДанными(Прокси, 
		СтруктураНастроекОбмена, ПараметрыПрокси, Отказ, СостояниеНастройки, СообщениеПользователю);
	
	Если Отказ Тогда
		СброситьПарольСинхронизацииДанных(Корреспондент);
		НастройкаСинхронизацииДанныхЗавершена = Ложь;
		Возврат Ложь;
	КонецЕсли;
	
	УстановитьПарольСинхронизацииДанных(Корреспондент, СтруктураНастроек.WSПароль);
	
	НастройкаСинхронизацииДанныхЗавершена   = СостояниеНастройки.НастройкаСинхронизацииДанныхЗавершена;
	ПолученоСообщениеДляСопоставленияДанных = СостояниеНастройки.ПолученоСообщениеДляСопоставленияДанных;
	
	Возврат СостояниеНастройки.НастройкаСуществует;
	
КонецФункции

Процедура ВыполнитьВыгрузкуДляУзлаИнформационнойБазыВСервисПередачиФайлов(ПараметрыПроцедуры, АдресХранилища) Экспорт
	
	ИмяПланаОбмена            = ПараметрыПроцедуры["ИмяПланаОбмена"];
	КодУзлаИнформационнойБазы = ПараметрыПроцедуры["КодУзлаИнформационнойБазы"];
	ИдентификаторФайла        = ПараметрыПроцедуры["ИдентификаторФайла"];
	
	ИспользоватьСжатие = ПараметрыПроцедуры.Свойство("ИспользоватьСжатие") И ПараметрыПроцедуры["ИспользоватьСжатие"];
	
	УстановитьПривилегированныйРежим(Истина);
	
	ИмяФайлаСообщения = ОбщегоНазначенияКлиентСервер.ПолучитьПолноеИмяФайла(
		ОбменДаннымиСервер.КаталогВременногоХранилищаФайлов(),
		ОбменДаннымиСервер.УникальноеИмяФайлаСообщенияОбмена());
	
	ПараметрыОбменаДанными = ОбменДаннымиСервер.ПараметрыОбменаДаннымиЧерезФайлИлиСтроку();
	
	ПараметрыОбменаДанными.ПолноеИмяФайлаСообщенияОбмена = ИмяФайлаСообщения;
	ПараметрыОбменаДанными.ДействиеПриОбмене             = Перечисления.ДействияПриОбмене.ВыгрузкаДанных;
	ПараметрыОбменаДанными.ИмяПланаОбмена                = ИмяПланаОбмена;
	ПараметрыОбменаДанными.КодУзлаИнформационнойБазы     = КодУзлаИнформационнойБазы;
	
	ОбменДаннымиСервер.ВыполнитьОбменДаннымиДляУзлаИнформационнойБазыЧерезФайлИлиСтроку(ПараметрыОбменаДанными);
	
	ИмяФайлаДляПомещенияВХранилище = ИмяФайлаСообщения;
	Если ИспользоватьСжатие Тогда
		ИмяФайлаДляПомещенияВХранилище = ОбщегоНазначенияКлиентСервер.ПолучитьПолноеИмяФайла(
			ОбменДаннымиСервер.КаталогВременногоХранилищаФайлов(),
			ОбменДаннымиСервер.УникальноеИмяФайлаСообщенияОбмена("zip"));
		
		Архиватор = Новый ЗаписьZipФайла(ИмяФайлаДляПомещенияВХранилище, , , , УровеньСжатияZIP.Максимальный);
		Архиватор.Добавить(ИмяФайлаСообщения);
		Архиватор.Записать();
		
		УдалитьФайлы(ИмяФайлаСообщения);
	КонецЕсли;
	
	ОбменДаннымиСервер.ПоместитьФайлВХранилище(ИмяФайлаДляПомещенияВХранилище, ИдентификаторФайла);
	
КонецПроцедуры

Процедура ВыполнитьЗагрузкуДляУзлаИнформационнойБазыИзСервисаПередачиФайлов(ПараметрыПроцедуры, АдресХранилища) Экспорт
	
	ИмяПланаОбмена            = ПараметрыПроцедуры["ИмяПланаОбмена"];
	КодУзлаИнформационнойБазы = ПараметрыПроцедуры["КодУзлаИнформационнойБазы"];
	ИдентификаторФайла        = ПараметрыПроцедуры["ИдентификаторФайла"];
	
	УстановитьПривилегированныйРежим(Истина);
	
	ИмяВременногоФайла = ОбменДаннымиСервер.ПолучитьФайлИзХранилища(ИдентификаторФайла);
	
	ПараметрыОбменаДанными = ОбменДаннымиСервер.ПараметрыОбменаДаннымиЧерезФайлИлиСтроку();
	
	ПараметрыОбменаДанными.ПолноеИмяФайлаСообщенияОбмена = ИмяВременногоФайла;
	ПараметрыОбменаДанными.ДействиеПриОбмене             = Перечисления.ДействияПриОбмене.ЗагрузкаДанных;
	ПараметрыОбменаДанными.ИмяПланаОбмена                = ИмяПланаОбмена;
	ПараметрыОбменаДанными.КодУзлаИнформационнойБазы     = КодУзлаИнформационнойБазы;
	
	Попытка
		ОбменДаннымиСервер.ВыполнитьОбменДаннымиДляУзлаИнформационнойБазыЧерезФайлИлиСтроку(ПараметрыОбменаДанными);
	Исключение
		ПредставлениеОшибки = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		УдалитьФайлы(ИмяВременногоФайла);
		ВызватьИсключение ПредставлениеОшибки;
	КонецПопытки;
	
	УдалитьФайлы(ИмяВременногоФайла);
КонецПроцедуры

// Соответствует операции UploadData
Процедура ВыполнитьВыгрузкуДанных(Прокси, ВерсияПрокси, СтруктураНастроекОбмена, ПараметрыОбмена) Экспорт
	
	Если Версия3_0_2_1(ВерсияПрокси) Тогда
		
		Прокси.UploadData(
			СтруктураНастроекОбмена.ИмяПланаОбменаКорреспондента,
			СтруктураНастроекОбмена.ТекущийУзелПланаОбменаКод,
			ПараметрыОбмена.ИдентификаторФайла,
			ПараметрыОбмена.ДлительнаяОперация,
			ПараметрыОбмена.ИдентификаторОперации,
			ПараметрыОбмена.ДлительнаяОперацияРазрешена,
			СтруктураНастроекОбмена.НастройкиТранспорта.WSОбластьДанныхКорреспондента);

	Иначе
					
		Прокси.UploadData(
			СтруктураНастроекОбмена.ИмяПланаОбмена,
			СтруктураНастроекОбмена.ТекущийУзелПланаОбменаКод,
			ПараметрыОбмена.ИдентификаторФайла,
			ПараметрыОбмена.ДлительнаяОперация,
			ПараметрыОбмена.ИдентификаторОперации,
			ПараметрыОбмена.ДлительнаяОперацияРазрешена);
			
	КонецЕсли;

КонецПроцедуры

// Соответствует операции DownloadData.
Процедура ВыполнитьЗагрузкуДанных(Прокси, ВерсияПрокси, СтруктураНастроекОбмена, ПараметрыОбмена, ИдентификаторФайлаСтрокой) Экспорт
	
	Если Версия3_0_2_1(ВерсияПрокси) Тогда
		
		Прокси.DownloadData(
			СтруктураНастроекОбмена.ИмяПланаОбменаКорреспондента,
			СтруктураНастроекОбмена.ТекущийУзелПланаОбменаКод,
			ИдентификаторФайлаСтрокой,
			ПараметрыОбмена.ДлительнаяОперация,
			ПараметрыОбмена.ИдентификаторОперации,
			ПараметрыОбмена.ДлительнаяОперацияРазрешена,
			СтруктураНастроекОбмена.НастройкиТранспорта.WSОбластьДанныхКорреспондента);
		
	Иначе
		
		Прокси.DownloadData(
			СтруктураНастроекОбмена.ИмяПланаОбмена,
			СтруктураНастроекОбмена.ТекущийУзелПланаОбменаКод,
			ИдентификаторФайлаСтрокой,
			ПараметрыОбмена.ДлительнаяОперация,
			ПараметрыОбмена.ИдентификаторОперации,
			ПараметрыОбмена.ДлительнаяОперацияРазрешена);
			
	КонецЕсли;

КонецПроцедуры

// Соответствует операции GetIBParameters.
Функция ПолучитьПараметрыИБ(Прокси, ВерсияПрокси, ИмяПланаОбмена, КодУзла, СообщениеОбОшибке,
	ОбластьДанных, ДополнительныеПараметры = Неопределено) Экспорт
	
	Если Версия3_0_2_2(ВерсияПрокси) Тогда
		
		Если ДополнительныеПараметры = Неопределено Тогда
			ДополнительныеПараметры = Новый Структура;
		КонецЕсли;
		
		ДополнительныеПараметрыXDTO = СериализаторXDTO.ЗаписатьXDTO(ДополнительныеПараметры);
		
		Возврат Прокси.GetIBParameters(ИмяПланаОбмена, КодУзла, СообщениеОбОшибке, ОбластьДанных, ДополнительныеПараметрыXDTO);
		
	ИначеЕсли Версия3_0_2_1(ВерсияПрокси) Тогда
		
		Возврат Прокси.GetIBParameters(ИмяПланаОбмена, КодУзла, СообщениеОбОшибке, ОбластьДанных);
			
	Иначе
		
		Возврат Прокси.GetIBParameters(ИмяПланаОбмена, КодУзла, СообщениеОбОшибке);
		
	КонецЕсли;
	
КонецФункции 

// Соответствует операции GetContinuousOperationStatus
Функция ПолучитьСтатусДлительнойОперации(Прокси, ВерсияПрокси, СтруктураНастроекОбмена, ПараметрыОбмена, СтрокаСообщенияОбОшибке) Экспорт
	
	Если Версия3_0_2_1(ВерсияПрокси) Тогда
		
		Возврат Прокси.GetContinuousOperationStatus(ПараметрыОбмена.ИдентификаторОперации,
			СтрокаСообщенияОбОшибке, 
			СтруктураНастроекОбмена.НастройкиТранспорта.WSОбластьДанныхКорреспондента);
		
	Иначе
	
		Возврат Прокси.GetContinuousOperationStatus(ПараметрыОбмена.ИдентификаторОперации, СтрокаСообщенияОбОшибке);
		
	КонецЕсли;
	
КонецФункции

// Соответствует операции PutMessageForDataMatching
Процедура ПоместитьСообщениеДляСопоставленияДанных(Прокси, ВерсияПрокси, СтруктураНастроекОбмена, ИдентификаторФайлаСтрокой) Экспорт
	
	Если Версия3_0_2_1(ВерсияПрокси) Тогда
		
		Прокси.PutMessageForDataMatching(СтруктураНастроекОбмена.ИмяПланаОбменаКорреспондента,
			СтруктураНастроекОбмена.ТекущийУзелПланаОбменаКод,
			ИдентификаторФайлаСтрокой,
			СтруктураНастроекОбмена.НастройкиТранспорта.WSОбластьДанныхКорреспондента);

		
	Иначе
		
		Прокси.PutMessageForDataMatching(СтруктураНастроекОбмена.ИмяПланаОбмена,
			СтруктураНастроекОбмена.ТекущийУзелПланаОбменаКод,
			ИдентификаторФайлаСтрокой);
	
	КонецЕсли;
	
КонецПроцедуры

// Соответствует операции RemoveExchangeNode
Процедура УдалитьУзелОбмена(Прокси, ВерсияПрокси, СтруктураНастроекОбмена) Экспорт
	
	Если Версия3_0_2_1(ВерсияПрокси) Тогда
		
		Прокси.RemoveExchangeNode(СтруктураНастроекОбмена.ИмяПланаОбменаКорреспондента,
			СтруктураНастроекОбмена.ТекущийУзелПланаОбменаКод,
			СтруктураНастроекОбмена.НастройкиТранспорта.WSОбластьДанныхКорреспондента);
			   
	Иначе
	
		Прокси.RemoveExchangeNode(СтруктураНастроекОбмена.ИмяПланаОбмена, СтруктураНастроекОбмена.ТекущийУзелПланаОбменаКод);
		
	КонецЕсли;
	
КонецПроцедуры

// Соответствует операции CreateExchangeNode
Процедура СоздатьУзелОбмена(Прокси, ВерсияПрокси, ПараметрыПодключения, ОбластьДанных) Экспорт
	
	Сериализатор = Новый СериализаторXDTO(Прокси.ФабрикаXDTO);
	
	Если Версия3_0_2_1(ВерсияПрокси) Тогда
		
		Прокси.CreateExchangeNode(Сериализатор.ЗаписатьXDTO(ПараметрыПодключения), ОбластьДанных);
		
	Иначе
		
		Прокси.CreateExchangeNode(Сериализатор.ЗаписатьXDTO(ПараметрыПодключения));
		
	КонецЕсли;
	
КонецПроцедуры

// Возвращаемое значение:
//   Строка
//
Функция СобытиеЖурналаРегистрацииУстановкаПодключенияКWebСервису() Экспорт
	
	Возврат НСтр("ru = 'Обмен данными.Установка подключения к web-сервису'", ОбщегоНазначения.КодОсновногоЯзыка());
	
КонецФункции

// Возвращаемое значение:
//   Строка
//
Функция СобытиеЖурналаРегистрацииУдалениеВременногоФайла() Экспорт
	
	Возврат НСтр("ru = 'Обмен данными.Удаление временного файла'", ОбщегоНазначения.КодОсновногоЯзыка());
	
КонецФункции

// Возвращаемое значение:
//   Строка
//
Функция СобытиеЖурналаРегистрацииИзменениеТранспортаНаWS() Экспорт
	
	Возврат НСтр("ru = 'Обмен данными.Изменение транспорта на WS'", ОбщегоНазначения.КодОсновногоЯзыка());
	
КонецФункции

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

Процедура ОжиданиеЗавершенияОперации(СтруктураНастроекОбмена, ПараметрыОбмена, Прокси, ПараметрыПрокси, ДействиеПриОбменеВЭтойИБ = Неопределено)
	
	Если ПараметрыОбмена.ИнтервалОжиданияНаСервере = 0 Тогда
		
		Если ДействиеПриОбменеВЭтойИБ <> Неопределено Тогда
			
			// В этой ИБ "Загрузка", значит в корреспонденте "Выгрузка"
			Если ДействиеПриОбменеВЭтойИБ = Перечисления.ДействияПриОбмене.ЗагрузкаДанных Тогда
				
				ДействиеВКорреспондентеСтрокой = НСтр("ru ='выгрузка'", ОбщегоНазначения.КодОсновногоЯзыка());
				
			Иначе
				
				ДействиеВКорреспондентеСтрокой = НСтр("ru ='загрузка'", ОбщегоНазначения.КодОсновногоЯзыка());
				
			КонецЕсли;
			
			ШаблонСообщения = НСтр("ru = 'Ожидание выполнения операции (%1 данных в базе-корреспонденте)...'", ОбщегоНазначения.КодОсновногоЯзыка());
			ОбменДаннымиСервер.ЗаписьЖурналаРегистрацииОбменаДанными(СтрШаблон(ШаблонСообщения, ДействиеВКорреспондентеСтрокой), СтруктураНастроекОбмена);
			
		КонецЕсли;
		
		Возврат;
		
	КонецЕсли;
	
	Пока ПараметрыОбмена.ДлительнаяОперация Цикл // Замена рекурсии
		
		ОбменДаннымиСервер.Пауза(ПараметрыОбмена.ИнтервалОжиданияНаСервере);
		
		СтрокаСообщенияОбОшибке = "";
	
		СостояниеОперации = ПолучитьСтатусДлительнойОперации(Прокси, ПараметрыПрокси.ТекущаяВерсия,
			СтруктураНастроекОбмена, ПараметрыОбмена, СтрокаСообщенияОбОшибке);
			
			Если СостояниеОперации = "Active" Тогда
			
			ПараметрыОбмена.ИнтервалОжиданияНаСервере = Мин(ПараметрыОбмена.ИнтервалОжиданияНаСервере + 30, 180);
			
		ИначеЕсли СостояниеОперации = "Completed" Тогда
			
			ПараметрыОбмена.ИнтервалОжиданияНаСервере = 15;
			ПараметрыОбмена.ДлительнаяОперация = Ложь; 
			ПараметрыОбмена.ИдентификаторОперации = Неопределено;
			
		Иначе
			
			ВызватьИсключение СтрШаблон(НСтр("ru = 'Ошибка в базе-корреспонденте:%1 %2'"), Символы.ПС, СтрокаСообщенияОбОшибке);
			
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

Функция Версия3_0_2_1(ВерсияПрокси)
	
	Возврат ОбщегоНазначенияКлиентСервер.СравнитьВерсии(ВерсияПрокси, "3.0.2.1") >= 0;
		
КонецФункции

Функция Версия3_0_2_2(ВерсияПрокси)
	
	Возврат ОбщегоНазначенияКлиентСервер.СравнитьВерсии(ВерсияПрокси, "3.0.2.2") >= 0;
		
КонецФункции


// Соответствует операции PrepareGetFile
Функция ПодготовитьФайлДляПолучения(Прокси, ВерсияПрокси, СтруктураНастроекОбмена,
	ИдентификаторФайла, РазмерЧасти, ИдентификаторСессии, КоличествоЧастей)
	
	Если Версия3_0_2_1(ВерсияПрокси) Тогда
		
		Возврат Прокси.PrepareGetFile(ИдентификаторФайла,
			РазмерЧасти,
			ИдентификаторСессии,
			КоличествоЧастей, 
			СтруктураНастроекОбмена.НастройкиТранспорта.WSОбластьДанныхКорреспондента);
		
	Иначе
	
		Возврат Прокси.PrepareGetFile(ИдентификаторФайла, РазмерЧасти, ИдентификаторСессии, КоличествоЧастей);
	
	КонецЕсли;
	
КонецФункции

// Соответствует операции GetFilePart
Процедура ПолучитьЧастьФайла(Прокси, ВерсияПрокси, СтруктураНастроекОбмена, ИдентификаторСессии, НомерЧасти, ДанныеЧасти)
	
	Если Версия3_0_2_1(ВерсияПрокси) Тогда
		
		Прокси.GetFilePart(ИдентификаторСессии,
			НомерЧасти, ДанныеЧасти,
			СтруктураНастроекОбмена.НастройкиТранспорта.WSОбластьДанныхКорреспондента);
			
	Иначе
	
		Прокси.GetFilePart(ИдентификаторСессии, НомерЧасти, ДанныеЧасти);
		
	КонецЕсли;
	
КонецПроцедуры

// Соответствует операции PutFilePart
Процедура ПоместитьЧастьФайла(Прокси, ВерсияПрокси, СтруктураНастроекОбмена, ИдентификаторСессии, НомерЧасти, ДанныеФайла)
	
	Если Версия3_0_2_1(ВерсияПрокси) Тогда
		
		Прокси.PutFilePart(ИдентификаторСессии, НомерЧасти, ДанныеФайла,
			СтруктураНастроекОбмена.НастройкиТранспорта.WSОбластьДанныхКорреспондента);
		
	Иначе
	
		Прокси.PutFilePart(ИдентификаторСессии, НомерЧасти, ДанныеФайла);
		
	КонецЕсли;
	
КонецПроцедуры

// Соответствует операции SaveFileFromParts
Процедура СобратьФайлИзЧастей(Прокси, ВерсияПрокси, СтруктураНастроекОбмена, ИдентификаторСессии, КоличествоЧастей, ИдентификаторФайла)
	
	Если Версия3_0_2_1(ВерсияПрокси) Тогда
		
		Прокси.SaveFileFromParts(ИдентификаторСессии, КоличествоЧастей, ИдентификаторФайла,
			СтруктураНастроекОбмена.НастройкиТранспорта.WSОбластьДанныхКорреспондента);
	Иначе
		
		Прокси.SaveFileFromParts(ИдентификаторСессии, КоличествоЧастей, ИдентификаторФайла);
		
	КонецЕсли; 
	
КонецПроцедуры

// Соответствует операции TestConnection
Функция ТестСоединения(Прокси, ВерсияПрокси, СтруктураНастроекОбмена, СообщениеОбОшибке)
	
	Если Версия3_0_2_1(ВерсияПрокси) Тогда
		
		Возврат Прокси.TestConnection(
			СтруктураНастроекОбмена.ИмяПланаОбменаКорреспондента, 
			СтруктураНастроекОбмена.ТекущийУзелПланаОбменаКод, 
			СообщениеОбОшибке, 
			СтруктураНастроекОбмена.НастройкиТранспорта.WSОбластьДанныхКорреспондента);
			
	Иначе
		
		Возврат Прокси.TestConnection(СтруктураНастроекОбмена.ИмяПланаОбмена,
			СтруктураНастроекОбмена.ТекущийУзелПланаОбменаКод,
			СообщениеОбОшибке);
		
	КонецЕсли;
	
КонецФункции

Процедура ПроверитьНедопустимыеСимволыВИмениПользователяWSПрокси(Знач ИмяПользователя)
	
	НедопустимыеСимволы = НедопустимыеСимволыВИмениПользователяWSПрокси();
	
	Если СтрокаСодержитСимвол(ИмяПользователя, НедопустимыеСимволы) Тогда
		
		СтрокаСообщения = НСтр("ru = 'В имени пользователя %1 содержатся недопустимые символы.
			|Имя пользователя не должно содержать символы %2.'");
		СтрокаСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(СтрокаСообщения, ИмяПользователя, НедопустимыеСимволы);
		
		ВызватьИсключение СтрокаСообщения;
		
	КонецЕсли;
	
КонецПроцедуры

Функция СтрокаСодержитСимвол(Знач Строка, Знач СтрокаСимволов)
	
	Для Индекс = 1 По СтрДлина(СтрокаСимволов) Цикл
		Символ = Сред(СтрокаСимволов, Индекс, 1);
		
		Если СтрНайти(Строка, Символ) <> 0 Тогда
			Возврат Истина;
		КонецЕсли;
	КонецЦикла;
	
	Возврат Ложь;
	
КонецФункции

Функция НедопустимыеСимволыВИмениПользователяWSПрокси()
	
	Возврат ":";
	
КонецФункции

Процедура ПроверитьКорректностьФорматаАдресаWSПрокси(Знач АдресWSПрокси)
	
	ЭтоИнтернетАдрес           = Ложь;
	ДопустимыеПрефиксыWSПрокси = ДопустимыеПрефиксыWSПрокси();
	
	Для Каждого Префикс Из ДопустимыеПрефиксыWSПрокси Цикл
		Если Лев(НРег(АдресWSПрокси), СтрДлина(Префикс)) = НРег(Префикс) Тогда
			ЭтоИнтернетАдрес = Истина;
			Прервать;
		КонецЕсли;
	КонецЦикла;
	
	Если Не ЭтоИнтернетАдрес Тогда
		СтрокаПрефиксов = "";
		Для Каждого Префикс Из ДопустимыеПрефиксыWSПрокси Цикл
			СтрокаПрефиксов = СтрокаПрефиксов + ?(ПустаяСтрока(СтрокаПрефиксов), """", " или """) + Префикс + """";
		КонецЦикла;
		
		СтрокаСообщения = НСтр("ru = 'Неверный формат адреса ""%1"".
			|Адрес должен начинаться с префикса Интернет протокола %2 (например: ""http://myserver.com/service"").'");
			
		СтрокаСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(СтрокаСообщения, АдресWSПрокси, СтрокаПрефиксов);
		
		ВызватьИсключение СтрокаСообщения;
	КонецЕсли;
	
КонецПроцедуры

Функция ДопустимыеПрефиксыWSПрокси()
	
	Результат = Новый Массив();
	
	Результат.Добавить("http");
	Результат.Добавить("https");
	
	Возврат Результат;
	
КонецФункции

Функция СостояниеНастройкиСинхронизацииВКорреспонденте(Прокси, ПараметрыПрокси, СтруктураНастроек)
	
	Результат = Новый Структура;
	Результат.Вставить("НастройкаСуществует",                     Ложь);
	
	Результат.Вставить("НастройкаСинхронизацииДанныхЗавершена",   Истина);
	Результат.Вставить("ПолученоСообщениеДляСопоставленияДанных", Ложь);
	Результат.Вставить("ПоддерживаетсяСопоставлениеДанных",       Истина);
		
	СтрокаСообщенияОбОшибке = "";
	Если ОбщегоНазначенияКлиентСервер.СравнитьВерсии(ПараметрыПрокси.ТекущаяВерсия, "2.0.1.6") >= 0 Тогда
		
		НастройкаСуществует = ТестСоединения(Прокси, ПараметрыПрокси.ТекущаяВерсия, СтруктураНастроек, СтрокаСообщенияОбОшибке);
		
		Если НастройкаСуществует
			И ОбщегоНазначенияКлиентСервер.СравнитьВерсии(ПараметрыПрокси.ТекущаяВерсия, "3.0.1.1") >= 0 Тогда
			
			ПараметрыПриемникаПрокси = ПолучитьПараметрыИБ(Прокси, ПараметрыПрокси.ТекущаяВерсия,
				СтруктураНастроек.ИмяПланаОбменаКорреспондента,
				СтруктураНастроек.ТекущийУзелПланаОбменаКод,
				СтрокаСообщенияОбОшибке,
				СтруктураНастроек.НастройкиТранспорта.WSОбластьДанныхКорреспондента);
			
			ПараметрыПриемника = СериализаторXDTO.ПрочитатьXDTO(ПараметрыПриемникаПрокси);
			
			ЗаполнитьЗначенияСвойств(Результат, ПараметрыПриемника);
		КонецЕсли;
		
		Результат.НастройкаСуществует = НастройкаСуществует;
	Иначе
		
		ПараметрыПриемникаПрокси = ПолучитьПараметрыИБ(Прокси, ПараметрыПрокси.ТекущаяВерсия,
				СтруктураНастроек.ИмяПланаОбмена,
				СтруктураНастроек.ТекущийУзелПланаОбменаКод,
				СтрокаСообщенияОбОшибке,
				СтруктураНастроек.НастройкиТранспорта.WSОбластьДанныхКорреспондента);
			
		ПараметрыПриемника = ЗначениеИзСтрокиВнутр(ПараметрыПриемникаПрокси);
		
		Если ПараметрыПриемника.Свойство("УзелСуществует") Тогда
			Результат.НастройкаСуществует = ПараметрыПриемника.УзелСуществует;
		Иначе
			Результат.НастройкаСуществует = Истина;
		КонецЕсли;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

Функция ВКорреспондентеУстаревшийВариантНастроекОбмена(Прокси, ПараметрыПрокси, СостояниеНастройки, СтруктураНастроек, КодУзла, Отказ, СтрокаСообщенияОбОшибке = "")
	
	СостояниеНастройкиВарианта = Новый Структура();
	СостояниеНастройкиВарианта.Вставить("НастройкиТранспорта", СтруктураНастроек.НастройкиТранспорта);
	
	// Проверка возможности выполнения перехода.
	Для Каждого ВариантНастройки Из УстаревшиеВариантыНастроекОбмена(СтруктураНастроек.УзелИнформационнойБазы) Цикл
		
		СостояниеНастройкиВарианта.Вставить("ИмяПланаОбмена", ВариантНастройки.ИмяПланаОбмена);
		СостояниеНастройкиВарианта.Вставить("ТекущийУзелПланаОбменаКод", КодУзла);
				
		СостояниеНастройки = СостояниеНастройкиСинхронизацииВКорреспонденте(
			Прокси, ПараметрыПрокси, СостояниеНастройкиВарианта);
		
		Если СостояниеНастройки.НастройкаСуществует Тогда
			Если СтруктураНастроек.ДействиеПриОбмене = Перечисления.ДействияПриОбмене.ВыгрузкаДанных Тогда
				СтруктураНастроек.ИмяПланаОбмена = ВариантНастройки.ИмяПланаОбмена;
				Если КодУзла <> СтруктураНастроек.ТекущийУзелПланаОбменаКод Тогда
					СтруктураНастроек.ТекущийУзелПланаОбменаКод = КодУзла;
				КонецЕсли;
			Иначе
				// В этой ИБ выполнен переход на новый план обмена, в корреспонденте еще не выполнен.
				// Получение данных необходимо отменить.
				СтрокаСообщенияОбОшибке = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'В программе ""%1"" выполняется обновление настроек синхронизации.
					|Загрузка данных отменена. Запустите синхронизацию данных повторно.'"),
					Строка(СтруктураНастроек.УзелИнформационнойБазы));
				Отказ = Истина;
			КонецЕсли;
			Возврат Истина;
		КонецЕсли;
	КонецЦикла;
	
	Возврат Ложь;
	
КонецФункции

Функция УстаревшиеВариантыНастроекОбмена(УзелОбмена)
	
	Результат = Новый Массив;
	
	ИмяПланаОбмена = ОбменДаннымиПовтИсп.ПолучитьИмяПланаОбмена(УзелОбмена);
	
	ВариантНастройки = "";
	Если ОбщегоНазначения.ЕстьРеквизитОбъекта("ВариантНастройки", УзелОбмена.Метаданные()) Тогда
		ВариантНастройки = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(УзелОбмена, "ВариантНастройки");
	КонецЕсли;
	
	Если ЗначениеЗаполнено(ВариантНастройки) Тогда
		Для Каждого ИмяСтарогоПланаОбмена Из ОбменДаннымиПовтИсп.ПланыОбменаБСП() Цикл
			Если ИмяСтарогоПланаОбмена = ИмяПланаОбмена Тогда
				Продолжить;
			КонецЕсли;
			Если ОбменДаннымиПовтИсп.ЭтоПланОбменаРаспределеннойИнформационнойБазы(ИмяСтарогоПланаОбмена) Тогда
				Продолжить;
			КонецЕсли;
			
			НастройкиСтарогоПланаОбмена = ОбменДаннымиСервер.ЗначениеНастройкиПланаОбмена(ИмяСтарогоПланаОбмена,
				"ИмяПланаОбменаДляПереходаНаНовыйОбмен,ВариантыНастроекОбмена");
			
			Если НастройкиСтарогоПланаОбмена.ИмяПланаОбменаДляПереходаНаНовыйОбмен = ИмяПланаОбмена Тогда
				ВариантНастроек = НастройкиСтарогоПланаОбмена.ВариантыНастроекОбмена.Найти(ВариантНастройки, "ИдентификаторНастройки");
				Если Не ВариантНастроек = Неопределено Тогда
					Результат.Добавить(Новый Структура("ИмяПланаОбмена, ИдентификаторНастройки", 
						ИмяСтарогоПланаОбмена, ВариантНастроек.ИдентификаторНастройки));
				КонецЕсли;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Устанавливает пароль синхронизации данных для заданного узла.
// Пароль сохраняется в параметре сеанса.
//
Процедура УстановитьПарольСинхронизацииДанных(Знач УзелИнформационнойБазы, Знач Пароль)
	
	УстановитьПривилегированныйРежим(Истина);
	
	ПаролиСинхронизацииДанных = Новый Соответствие;
	
	Для Каждого Элемент Из ПараметрыСеанса.ПаролиСинхронизацииДанных Цикл
		
		ПаролиСинхронизацииДанных.Вставить(Элемент.Ключ, Элемент.Значение);
		
	КонецЦикла;
	
	ПаролиСинхронизацииДанных.Вставить(УзелИнформационнойБазы, Пароль);
	
	ПараметрыСеанса.ПаролиСинхронизацииДанных = Новый ФиксированноеСоответствие(ПаролиСинхронизацииДанных);
	
КонецПроцедуры

// Сбрасывает пароль синхронизации данных для заданного узла.
//
Процедура СброситьПарольСинхронизацииДанных(Знач УзелИнформационнойБазы)
	
	УстановитьПарольСинхронизацииДанных(УзелИнформационнойБазы, Неопределено);
	
КонецПроцедуры

#КонецОбласти

